﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace YasharEl.Infrastructure.EntityModel
{
    /// <summary>
    /// The interface represents unit of work pattern implementation.
    /// </summary>
    public interface IUnitOfWork : IDisposable
    {
        /// <summary>
        /// Flushes content of unit of work to the underlying data storage. Causes unsaved
        /// entities to be written to the data storage.
        /// </summary>
        void Flush();

        /// <summary>
        /// Begins the transaction.
        /// </summary>
        ITransaction BeginTransaction();

        /// <summary>
        /// Ends transaction.
        /// Note: suggested pattern to manage a transaction is via *using* construct.
        /// You should set input param to null after calling the method.
        /// </summary>
        /// <example>
        /// using ( var tnx = uow.BeginTransaction() ) { /* do some work */ }
        /// </example>
        /// See also <seealso cref="ITransaction"/> interface for more details.
        void EndTransaction(ITransaction transaction);

        /// <summary>
        /// Inserts entity to the storage.
        /// </summary>
        void Insert<TEntity, TIdentity>(TEntity entity) where TEntity : class, IGenericEntity<TIdentity>;

        /// <summary>
        /// Updates entity in the storage.
        /// </summary>
        void Update<TEntity, TIdentity>(TEntity entity) where TEntity : class, IGenericEntity<TIdentity>;

        /// <summary>
        /// Deletes entity in the storage.
        /// </summary>
        void Delete<TEntity, TIdentity>(TEntity entity) where TEntity : class, IGenericEntity<TIdentity>;

        /// <summary>
        /// Gets entity from the storage by it's Id.
        /// </summary>
        TEntity GetById<TEntity, TIdentity>(TIdentity id) where TEntity : class, IGenericEntity<TIdentity>;

        IList<TEntity> GetAll<TEntity, TIdentity>() where TEntity : class, IGenericEntity<TIdentity>;

        IQueryable<TEntity> ToQueryable<TEntity, TIdentity>() where TEntity : class, IGenericEntity<TIdentity>;

        void ExecuteTransactional(Action action);
    }
}
